import { AudioClip, AudioSource, director, find,Node } from "cc";
import { Singleton } from "./Singleton";
import { LoaderBundle } from "./LoaderBundle";

export default class AudioManager extends Singleton{
    private _audioSources:Array<AudioSource>;
    private _musicSource:AudioSource

    private _node:Node;
    private _effect:Node;

    private soundVol:number=1;
    private musicVol:number=1;

    private _bundleLoad:LoaderBundle;
    /**
     * 进入游戏设置
     * @param bundleName 
     */
    public setBundle(load:LoaderBundle){
        this._bundleLoad=load;
    
    } 
  
    private getClicp(path:string):Promise<AudioClip>{
        return new Promise<AudioClip>(async (resolve)=>{
            let clip:AudioClip = await this._bundleLoad.load(path,AudioClip)
            resolve(clip);
        });
    } 
    init(){ 
        this._audioSources=new Array();
        this._node=find("GLSoundNode")
        if(!this._node){
            this._node=new Node("GLSoundNode") 
            this._effect = new Node("GLSoundEffectNode") 
            director.addPersistRootNode(this._node)
            director.addPersistRootNode(this._effect)
        }
        
    } 
    private getEffectSource():AudioSource{
        if(this._audioSources.length > 4){ 
            for(let i=0;i<this._audioSources.length;i++){
                if(this._audioSources[i] && !this._audioSources[i].playing){
                    this._audioSources[i].destroy();
                    this._audioSources[i]=null; 
                    this._audioSources.splice(i,1) 
                    break
                }
            } 
        }
       
        let source:AudioSource = this._effect.addComponent(AudioSource);
        this._audioSources.push(source);
        return source;
    }

    /**
     * 播放音乐
     * @param path 
     * @param vol 
     * @returns 
     */
    playMusic(path:string|AudioClip):Promise<void>{
        return new Promise(async resolve=>{
            let clip:AudioClip=path as AudioClip; 
            if(typeof path == "string"){ 
                clip=await this.getClicp(path)
            }  
            if(this._musicSource){
                this._musicSource.destroy();
                this._musicSource=null  
            }
            this._musicSource = this._node.addComponent(AudioSource)
            
            this._musicSource["path"]=path
            this._musicSource.loop=true 
            if(this._musicSource && this._musicSource.isValid && clip && clip.isValid){
                this._musicSource.clip=clip;
                this._musicSource.volume=this.musicVol
                this._musicSource.play();
            }
            
            resolve();
        })
    }
    /**  
     * 停止音乐 
     */ 
    stopMusic(){ 
        if(this._musicSource){
            this._musicSource.destroy();
            this._musicSource.stop();
            this._musicSource=null  
        }
    }
    /**
     * 暂停音乐
     */
    pauseMusic(){
        if(this._musicSource)this._musicSource.pause();
    }
    /**
     * 回复暂停的音乐
     */
    resumeMusic(){
        if(this._musicSource)this._musicSource.play();
    }
    /**
     *  设置音量
     * @param vol 
     */
    setMusicVol(vol:number){
        this.musicVol=vol;
        if(this._musicSource)this._musicSource.volume=vol;
    }
    /**
     * 播放音效
     * @param path 
     * @param vol 
     * @returns 
     */ 
    playEffect(path:string|AudioClip,isLoop:boolean=false):Promise<void>{
       return new Promise(async resolve=>{
            let source:AudioSource=this.getEffectSource();
            if(!source){
                resolve();
                return
            } 
            let clip:AudioClip=path as AudioClip;
            if(typeof path == "string"){
                clip=await this.getClicp(path)
            }
            source["use"]=true
            source["path"]=path
            source.loop=isLoop
            if(source && source.isValid && clip && clip.isValid){
                source.clip=clip; 
                source.volume=this.soundVol
                source.play();
            }
            resolve(); 
       })
    }
     /**
     *  设置音量
     * @param vol 
     */
    setSoundVol(vol:number){
        this.soundVol=vol;
        if(!this._audioSources || this._audioSources.length <= 0 )return
        for(let i=0;i<this._audioSources.length;i++){
            if(this._audioSources[i])this._audioSources[i].volume=vol
        }
    }
    pauseSound(){
        if(!this._audioSources || this._audioSources.length <= 0 )return
        for(let i=0;i<this._audioSources.length;i++){
            if(this._audioSources[i])this._audioSources[i].pause();
        }
    }
     /**
     * 回复暂停的音乐 
     */
     resumeSound(){
        if(!this._audioSources || this._audioSources.length <= 0 )return
        for(let i=0;i<this._audioSources.length;i++){
            if(this._audioSources[i])this._audioSources[i].play();
        }
     }

     stopSound(path:string){
        for(let i=0;i<this._audioSources.length;i++){
            if(this._audioSources[i] && this._audioSources[i]["path"] == path){
                this._audioSources[i].stop()
                this._audioSources[i].clip=null;
                break
            }
        }
     }
     /**
      * 停止全部音乐
      */
     stopAllSound(){
        for(let i=0;i<this._audioSources.length;i++){
            if(this._audioSources[i]){
                this._audioSources[i].stop()
                this._audioSources[i].clip=null;
            }
        }
     }
}